import { defineStore } from 'pinia';
import { getToken, removeToken, setToken } from '../utils/token-utils';
import type { UserInfoState } from './interface';
import { ElMessage } from 'element-plus';
import { allAsyncRoutes, anyRoute, staticRoutes } from '@/router/routes';
import { getUserInfoApi, loginApi, logoutApi } from '@/api/acl/login';
import type { RouteRecordRaw } from 'vue-router';
import router from '@/router';
import { cloneDeep } from 'lodash';

/* 
  对所有的异步路由进行过滤得到用户的权限路由表
*/
function filterAsyncRoutes(
  allAsyncRoutes: RouteRecordRaw[],
  routeName: string[]
): RouteRecordRaw[] {
  return allAsyncRoutes.filter((route) => {
    // 如果route的name没有在routeName中，过滤它(返回false)
    if (!routeName.includes(route.name as string)) return false;

    // 如果当前route有子路由，需要子路由进行递归调用
    if (route.children && route.children.length > 0) {
      route.children = filterAsyncRoutes(route.children, routeName); // 一定要对children进行重新赋值
    }

    // 否则返回true
    return true;
  });
}

// 注册指定的路由表
function addRoutes(routes: RouteRecordRaw[]) {
  routes.forEach((route) => router.addRoute(route));
}

// 重置路由 只注册静态的初始路由
function resetRoute() {
  // 得到所有已经注册的路由，根据路由的name进行删除
  router
    .getRoutes()
    .forEach((route) => route.name && router.removeRoute(route.name));

  // 重新注册静态路由
  addRoutes(staticRoutes);
}

/**
 * 用户信息
 * @methods setUserInfos 设置用户信息
 */
export const useUserInfoStore = defineStore('userInfo', {
  state: (): UserInfoState => ({
    token: getToken() as string,
    name: '',
    avatar: '',
    menuRoutes: [], // 用于生成导航菜单的路由表
    buttons: [],
    roles: [],
  }),

  actions: {
    // 登陆的异步action
    async login(username: string, password: string) {
      // 发送登陆的请求
      const result = await loginApi(username, password);
      // 请求成功后, 取出token保存  pinia和local中
      const token = result.token;
      this.token = token;
      setToken(token);
    },

    async getInfo() {
      // 请求获取用户信息
      const result = await getUserInfoApi();
      // 请求成功后, 读取用户信息name和avatar, 保存到state
      const { name, avatar, routes, buttons, roles } = result;
      this.name = name;
      this.avatar = avatar;

      // 保存按钮权限列表和角色列表
      this.buttons = buttons;
      this.roles = roles;

      // 根据路由权限数据routes从allAsyncRoutes过滤出来用户权限路由表，进行动态注册
      const asyncRoutes = filterAsyncRoutes(cloneDeep(allAsyncRoutes), routes);

      // 最后注册通配路由
      addRoutes([...asyncRoutes, anyRoute]);

      // 根据静态路由表+ 用户权限路由表合并生成权限导航菜单
      this.menuRoutes = [...staticRoutes, ...asyncRoutes];
    },

    async reset() {
      // 如果当前有用户名, 请求退出登陆接口
      if (this.name) {
        await logoutApi(); // 加await后, 下面的代码是在请求成功后执行的
      }

      // 删除local中保存的token
      removeToken();
      // 提交重置用户信息的mutation
      this.token = '';
      this.name = '';
      this.avatar = '';

      this.menuRoutes = []; // 清空菜单路由列表
      this.buttons = []; // 按钮权限列表
      // 重置注册的路由 =》 只注册静态路由，清除动态注册的路由
      resetRoute();
    },
  },
});
